/*
 * GameMap - A tile-based map and container for other location-based
 * data
 *
 * Copyright 2008 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package rules;

import lib3f.IntPoint;
import lib3f.LCG;

class GameMap
{
	
	inline public static var mapxsize = 42;
	inline public static var mapysize = 42;
	inline public static var mapmaxref = mapxsize - 1;
	inline public static var mapmayref = mapysize - 1;
	
	inline public static var mapxcenter = Std.int(mapxsize / 2) - 1;
	inline public static var mapycenter = Std.int(mapysize / 2) - 1;

	inline public static var corners = [[0,0],[mapmaxref,0],
			[0,mapmayref],[mapmaxref,mapmayref]];
	
	public var tiles : Array<Array<GameTile>>;
	public var spawntoshore : Array<Array<IntPoint>>;
	public var shoretocenter : Array<Array<IntPoint>>;
	public var iter : Array<GameTile>;
	
	public function new()
	{
		tiles = new Array();
		iter = new Array();
		
		for (x in 0...mapxsize)
		{
			tiles.push(new Array());
			for (y in 0...mapysize)
			{
				tiles[x].push(new GameTile(x,y));
				iter.push(tiles[x][y]);
			}			
		}

		for (n in iter)
				n.setneighbors(tiles);

	}

	public function addbase(centertile : GameTile)
	{

		var newfort = new FortressData(FortressData.fort_base);
		centertile.fort = newfort;
		newfort.x = centertile.x;
		newfort.y = centertile.y;
		
		if (centertile.terrain==GameTile.ter_space)
			centertile.terrain=GameTile.ter_ground;
		
		for (n in centertile.neighbors)
		{
			var newfort = new FortressData(FortressData.fort_line);
			n.fort = newfort;
			newfort.x = n.x;
			newfort.y = n.y;
			
			if (n.terrain==GameTile.ter_space)
				n.terrain=GameTile.ter_ground;
		}
		
	}

	inline public static var mapgen_numstrips = 12;
	inline public static var mapgen_striplength = 80;
	inline public static var mapgen_qtyenergy = 8; 
	inline public static var mapgen_borderofland = 6;

	public function genmap(?seed : Int)
	{
		
		var lcg = RulesAPI.g.lcg;
		
		for (n in 0...mapgen_numstrips)
		{
			var curloc = tiles[mapxcenter][mapycenter];
			var direction = lcg.randInt(5);
			for (times in 0...mapgen_striplength)
			{
				direction = lcg.randInt(5);
				curloc.terrain = 
					GameTile.ter_ground;
				var next = tiles[curloc.x][curloc.y].neighbors
					[direction];
				while (next.x<=mapgen_borderofland
				    || next.y<=mapgen_borderofland
				    || next.x>mapmaxref-mapgen_borderofland
					|| next.y>mapmayref-mapgen_borderofland)
				{
					direction = lcg.randInt(5);
					next = tiles[curloc.x][curloc.y].neighbors
					[direction];
				}
				curloc = next;
			}
		}

		for (n in 0...mapgen_qtyenergy)
		{
				var next = tiles[lcg.randInt(mapmaxref)]
								[lcg.randInt(mapmayref)];
				while (next.x<=mapgen_borderofland
				    || next.y<=mapgen_borderofland
				    || next.x>mapmaxref-mapgen_borderofland
					|| next.y>mapmayref-mapgen_borderofland
					||
					!(next.groundnearby())
					)
				{
					next = tiles[lcg.randInt(mapmaxref)]
								[lcg.randInt(mapmayref)];				
				}	
				next.terrain = GameTile.ter_energy;
		}
		
	}
	
	public function calcshoreinner() : Array<IntPoint>
	{
		var result : Array<IntPoint> = new Array();
		for (n in iter)
		{
			// if the tile is not space
			// and there is a space tile nearby
			if (n.terrain != GameTile.ter_space &&
				n.spacenearby())
				result.push(new IntPoint(n.x,n.y));
		}
		return result;
	}

	public function calcshoreouter() : Array<IntPoint>
	{
		var result : Array<IntPoint> = new Array();
		for (n in iter)
		{
			// in english:
			// if the tile is space
			// and if a non-space tile is near
			// and if the tile is accessable from spawnshorepaths
			if (n.terrain == GameTile.ter_space &&
				!n.noground() && 
				(RulesAPI.g.creepspawnshorepaths[0].nodes
				  [n.x][n.y].value
				  !=-1))
				result.push(new IntPoint(n.x,n.y));
		}		
		return result;
	}

	inline public static function inbounds(x : Int, y : Int) : Bool
	{
		if (x>=0 && x<=mapmaxref && y>=0 && y<=mapmayref)
		 return true;
		else
		 return false;
	}
		
}
